home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-13 | 17.0 KB | 744 lines | [TEXT/PJMM] |
- unit DemoMenus;
-
- { WASTE DEMO PROJECT: }
- { Menu Handling }
-
- { Copyright © 1993-1994 Merzwaren }
- { All Rights Reserved }
-
- interface
- uses
- DemoIntf;
-
- function InitializeMenus: OSErr;
- procedure PrepareMenus;
- procedure DoMenuChoice (menuChoice: LongInt);
- function DoClose (closing: ClosingOption;
- saving: SavingOption;
- window: WindowPtr): OSErr;
- function DoQuit (saving: SavingOption): OSErr;
-
- implementation
- uses
- Aliases, DemoFiles, DemoWindows, DialogUtils, Script;
-
- procedure SetDefaultDirectory (vRefNum: Integer;
- dirID: LongInt);
-
- { Q&D inline to set the default volume and directory used by Standard File }
- { I'm afraid this may not work under System >= 7.5 or with certain third-party extensions }
-
- inline
- $21DF, $0398, { move.l (sp)+, CurDirStore }
- $301F, { move.w (sp)+, d0 }
- $4440, { neg.w d0 }
- $31C0, $0214; { move.w d0, SFSaveDisk }
-
- function SFDialogFilter (dialog: DialogPtr;
- var event: EventRecord;
- var item: Integer;
- yourData: Ptr): Boolean;
- begin
- SFDialogFilter := DialogFilter(dialog, event, item);
- end; { SFDialogFilter }
-
- function FindMenuItem (menu: MenuHandle;
- stringToFind: Str255): Integer;
- var
- item: Integer;
- itemString: Str255;
- begin
- for item := CountMItems(menu) downto 1 do
- begin
- GetItem(menu, item, itemString);
- if EqualString(itemString, stringToFind, false, false) then
- Leave;
- end;
- FindMenuItem := item;
- end; { FindMenuItem }
-
- procedure PrepareMenus;
- var
- window: WindowPtr;
- menu: MenuHandle;
- item: Integer;
- itemString: Str255;
- selStart, selEnd: LongInt;
- actionKind: WEActionKind;
- mode: Integer;
- ts: TextStyle;
- temp: Boolean;
- alignment: SignedByte;
- begin
-
- { get a pointer to the frontmost window, if any }
- window := FrontWindow;
-
- { *** FILE MENU *** }
- menu := GetMHandle(kMenuFile);
-
- { first disable all items }
- for item := CountMItems(menu) downto 1 do
- DisableItem(menu, item);
-
- { New, Open and Quit are always enabled }
- EnableItem(menu, kItemNew);
- EnableItem(menu, kItemOpen);
- EnableItem(menu, kItemQuit);
-
- { enable Close and Save As if there is an active window }
- if (window <> nil) then
- begin
- EnableItem(menu, kItemClose);
- EnableItem(menu, kItemSaveAs);
-
- { enable Save if the active window is dirty and has an associated file }
- if (WEGetModCount(DocumentPeek(window)^.hWE) > 0) and (DocumentPeek(window)^.fileAlias <> nil) then
- EnableItem(menu, kItemSave);
- end;
-
- { *** EDIT MENU *** }
- menu := GetMHandle(kMenuEdit);
-
- { first disable all items }
- for item := CountMItems(menu) downto 1 do
- DisableItem(menu, item);
-
- { by default, the Undo menu item should read "Can't Undo" }
- GetIndString(itemString, kUndoStringsID, 1);
- SetItem(menu, kItemUndo, itemString);
-
- if (window <> nil) then
- begin
-
- { enable Paste if there's anything pasteable on the Clipboard }
- if (WECanPaste) then
- EnableItem(menu, kItemPaste);
-
- { enable Undo if anything can be undone }
- actionKind := WEGetUndoInfo(temp, DocumentPeek(window)^.hWE);
- if (actionKind <> weAKNone) then
- begin
- EnableItem(menu, kItemUndo);
-
- { change the Undo menu item to "Undo"/"Redo" + name of action to undo }
- GetIndString(itemString, kUndoStringsID, 2 * actionKind + ORD(temp));
- SetItem(menu, kItemUndo, itemString);
- end;
-
- { enable Select All if there is anything to select }
- if (WEGetTextLength(DocumentPeek(window)^.hWE) > 0) then
- EnableItem(menu, kItemSelectAll);
-
- { get the current selection range }
- WEGetSelection(selStart, selEnd, DocumentPeek(window)^.hWE);
- if (selStart <> selEnd) then
- begin
-
- { enable Cut, Copy and Clear if the selection range is not empty }
- EnableItem(menu, kItemCut);
- EnableItem(menu, kItemCopy);
- EnableItem(menu, kItemClear);
- end;
-
- { determine which style attributes are continuous over the current selection range }
- { we'll need this information in order to check the Font/Size/Style menus properly }
- mode := weDoFont + weDoSize + weDoFace; { query about these attributes }
- temp := WEContinuousStyle(mode, ts, DocumentPeek(window)^.hWE);
- end
- else
- mode := 0; { no window; so check no item }
-
- { *** FONT MENU *** }
- menu := GetMHandle(kMenuFont);
-
- { first remove all check marks }
- for item := CountMItems(menu) downto 1 do
- CheckItem(menu, item, false);
-
- { if there is a continuous font all over the selection range, }
- { check the corresponding menu item }
- if (BitAnd(mode, weDoFont) <> 0) then
- begin
- GetFontName(ts.tsFont, itemString);
- CheckItem(menu, FindMenuItem(menu, itemString), true);
- end;
-
- { *** SIZE MENU *** }
- menu := GetMHandle(kMenuSize);
-
- { first remove all check marks }
- for item := CountMItems(menu) downto 1 do
- CheckItem(menu, item, false);
-
- { if there is a continuous font size all over the selection range, }
- { check the corresponding menu item }
- if (BitAnd(mode, weDoSize) <> 0) then
- begin
- NumToString(ts.tsSize, itemString);
- CheckItem(menu, FindMenuItem(menu, itemString), true);
- end;
-
- { *** STYLE MENU *** }
- menu := GetMHandle(kMenuStyle);
-
- { first remove all check marks }
- for item := CountMItems(menu) downto 1 do
- CheckItem(menu, item, false);
-
- { check the Style menu items corresponding to style attributes }
- { which are continuous over the current selection range }
- if (BitAnd(mode, weDoFace) <> 0) then
- begin
-
- if (ts.tsFace = []) then
- CheckItem(menu, kItemPlainText, true);
-
- if (bold in ts.tsFace) then
- CheckItem(menu, kItemBold, true);
-
- if (italic in ts.tsFace) then
- CheckItem(menu, kItemItalic, true);
-
- if (underline in ts.tsFace) then
- CheckItem(menu, kItemUnderline, true);
-
- if (outline in ts.tsFace) then
- CheckItem(menu, kItemOutline, true);
-
- if (shadow in ts.tsFace) then
- CheckItem(menu, kItemShadow, true);
-
- if (condense in ts.tsFace) then
- CheckItem(menu, kItemCondensed, true);
-
- if (extend in ts.tsFace) then
- CheckItem(menu, kItemExtended, true);
-
- end;
-
- { *** ALIGNMENT MENU *** }
- menu := GetMHandle(kMenuAlignment);
-
- { first remove all check marks }
- for item := CountMItems(menu) downto 1 do
- CheckItem(menu, item, false);
-
- if (window <> nil) then
- begin
-
- { get the current alignment style }
- alignment := WEGetAlignment(DocumentPeek(window)^.hWE);
-
- { find the corresponding Alignment menu item }
- case alignment of
-
- weFlushLeft:
- item := kItemAlignLeft;
-
- weFlushRight:
- item := kItemAlignRight;
-
- weFlushDefault:
- if (GetSysJust = 0) then
- item := kItemAlignLeft
- else
- item := kItemAlignRight;
-
- weCenter:
- item := kItemCenter;
-
- weJustify:
- item := kItemJustify;
-
- end; { case }
-
- { check the menu item }
- CheckItem(menu, item, true);
-
- end;
- end; { PrepareMenus }
-
- procedure DoAbout;
- var
- alertResult: Integer;
- begin
- SetCursor(arrow);
- alertResult := Alert(kAlertAboutBox, @DialogFilter);
- end; { DoAbout }
-
- procedure DoDeskAcc (menuItem: Integer);
- var
- daName: Str255;
- daNumber: Integer;
- begin
- GetItem(GetMHandle(kMenuApple), menuItem, daName);
- daNumber := OpenDeskAcc(daName);
- end; { DoDeskAcc }
-
- function DoNew: OSErr;
- begin
-
- { create a new window from scratch }
- DoNew := CreateWindow(nil);
- end; { DoNew }
-
- function DoOpen: OSErr;
- var
- reply: StandardFileReply;
- typeList: SFTypeList;
- begin
- DoOpen := noErr;
-
- { set up a list of file types we can open for StandardGetFile }
- typeList[0] := kTypeText;
-
- { put up the standard Open dialog box }
- { (we use CustomGetFile instead of StandardGetFile because we want to provide }
- { our own dialog filter procedure that takes care of updating our windows) }
- CustomGetFile(nil, 1, typeList, reply, 0, Point(-1), nil, @SFDialogFilter, nil, nil, nil);
-
- { if the user okayed the dialog, create a new window from the specified file }
- if (reply.sfGood) then
- DoOpen := CreateWindow(@reply.sfFile)
- else
- DoOpen := userCanceledErr;
-
- end; { DoOpen }
-
- function DoSaveAs (suggestedTarget: FSSpecPtr;
- window: WindowPtr): OSErr;
- var
- hPrompt: StringHandle;
- defaultName: Str255;
- reply: StandardFileReply;
- err: OSErr;
- begin
- DoSaveAs := noErr;
-
- { get the prompt string for CustomPutFile from a 'STR ' resource and lock it }
- hPrompt := GetString(kPromptStringID);
- HLockHi(Handle(hPrompt));
-
- { if a suggested target file is provided, use its name as the default name }
- if (suggestedTarget <> nil) then
- begin
- defaultName := suggestedTarget^.name;
- SetDefaultDirectory(suggestedTarget^.vRefNum, suggestedTarget^.parID);
- end
- else
-
- { otherwise use the window title as default name for CustomPutFile }
- GetWTitle(window, defaultName);
-
- { put up the standard Save dialog box }
- CustomPutFile(hPrompt^^, defaultName, reply, 0, Point(-1), nil, @SFDialogFilter, nil, nil, nil);
-
- { unlock the string resource }
- HUnlock(Handle(hPrompt));
-
- { if the user okayed the dialog, update the file alias }
- { and save the window to the specified file }
- if (reply.sfGood) then
- begin
- ForgetHandle(DocumentPeek(window)^.fileAlias);
- err := NewAlias(nil, reply.sfFile, AliasHandle(DocumentPeek(window)^.fileAlias));
- if (err <> noErr) then
- begin
- DoSaveAs := err;
- Exit(DoSaveAs);
- end;
- SetWTitle(window, reply.sfFile.name);
- DoSaveAs := WriteTextFile(@reply.sfFile, DocumentPeek(window)^.hWE);
- end
- else
- DoSaveAs := userCanceledErr;
-
- end; { DoSaveAs }
-
- function DoSave (window: WindowPtr): OSErr;
- var
- spec: FSSpec;
- suggestedTarget: FSSpecPtr;
- promptForNewFile, aliasTargetWasChanged: Boolean;
- begin
- DoSave := noErr;
- suggestedTarget := nil;
- promptForNewFile := true;
-
- { resolve the alias associated with this window, if any }
- if (DocumentPeek(window)^.fileAlias <> nil) then
- if (ResolveAlias(nil, AliasHandle(DocumentPeek(window)^.fileAlias), spec, aliasTargetWasChanged) = noErr) then
- if (aliasTargetWasChanged) then
- suggestedTarget := @spec
- else
- promptForNewFile := false;
-
- { if no file has been previously associated with this window, }
- { or if the alias resolution has failed, or if the alias target was changed, }
- { prompt the user for a new destination }
- if (promptForNewFile) then
- DoSave := DoSaveAs(suggestedTarget, window)
- else
- DoSave := WriteTextFile(@spec, DocumentPeek(window)^.hWE);
-
- end; { DoSave }
-
- function DoClose (closing: ClosingOption;
- saving: SavingOption;
- window: WindowPtr): OSErr;
- const
- kButtonSave = 1;
- kButtonCancel = 2;
- kButtonDontSave = 3;
- var
- s: Str255;
- alertResult: Integer;
- err: OSErr;
- begin
- DoClose := noErr;
-
- { is this window dirty? }
- if (WEGetModCount(DocumentPeek(window)^.hWE) > 0) then
- begin
-
- { do we have to ask the user whether to save changes? }
- if (saving = savingAsk) then
- begin
-
- { prepare the parametric strings to be used in the Save Changes alert box }
- GetWTitle(window, s);
- ParamText(s, StringPtr(nil)^, StringPtr(nil)^, StringPtr(nil)^);
- GetIndString(s, kClosingQuittingStringsID, 1 + ORD(closing));
- ParamText(StringPtr(nil)^, s, StringPtr(nil)^, StringPtr(nil)^);
-
- { put up the Save Changes? alert box }
- SetCursor(arrow);
- alertResult := Alert(kAlertSaveChanges, @DialogFilter);
-
- { exit if the user canceled the alert box }
- if (alertResult = kButtonCancel) then
- begin
- DoClose := userCanceledErr;
- Exit(DoClose);
- end;
-
- if (alertResult = kButtonSave) then
- saving := savingYes
- else
- saving := savingNo;
- end; { if saving = savingAsk }
-
- if (saving = savingYes) then
- begin
- err := DoSave(window);
- if (err <> noErr) then
- begin
- DoClose := err;
- Exit(DoClose);
- end;
- end;
- end; { if window is dirty }
-
- { destroy the window }
- DestroyWindow(window);
-
- end; { DoClose }
-
- function DoQuit (saving: SavingOption): OSErr;
- var
- window: WindowPtr;
- err: OSErr;
- begin
- DoQuit := noErr;
-
- { close all open windows }
- repeat
- window := FrontWindow;
- if (window <> nil) then
- begin
- err := DoClose(closingApplication, saving, window);
- if (err <> noErr) then
- begin
- DoQuit := err;
- Exit(DoQuit);
- end;
- end;
- until (window = nil);
-
- { set a flag so we drop out of the event loop }
- gExiting := true;
-
- end; { DoQuit }
-
- procedure DoAppleChoice (menuItem: Integer);
- begin
- if (menuItem = kItemAbout) then
- DoAbout
- else
- DoDeskAcc(menuItem);
- end; { DoAppleChoice }
-
- procedure DoFileChoice (menuItem: Integer);
- begin
- case menuItem of
-
- kItemNew:
- if (DoNew <> noErr) then
- ;
-
- kItemOpen:
- if (DoOpen <> noErr) then
- ;
-
- kItemClose:
- if (DoClose(closingWindow, savingAsk, FrontWindow) <> noErr) then
- ;
-
- kItemSave:
- if (DoSave(FrontWindow) <> noErr) then
- ;
-
- kItemSaveAs:
- if (DoSaveAs(nil, FrontWindow) <> noErr) then
- ;
-
- kItemQuit:
- if (DoQuit(savingAsk) <> noErr) then
- ;
-
- otherwise
- ;
- end; { case menuItem }
- end; { DoFileChoice }
-
- procedure DoEditChoice (menuItem: Integer);
- var
- window: WindowPtr;
- hWE: WEHandle;
- begin
-
- { do nothing if no window is active }
- window := FrontWindow;
- if (window = nil) then
- Exit(DoEditChoice);
- hWE := DocumentPeek(window)^.hWE;
-
- case menuItem of
-
- kItemUndo:
- if (WEUndo(hWE) <> noErr) then
- ;
-
- kItemCut:
- if (WECut(hWE) <> noErr) then
- ;
-
- kItemCopy:
- if (WECopy(hWE) <> noErr) then
- ;
-
- kItemPaste:
- if (WEPaste(hWE) <> noErr) then
- ;
-
- kItemClear:
- if (WEDelete(hWE) <> noErr) then
- ;
-
- kItemSelectAll:
- WESetSelection(0, maxLongInt, hWE);
-
- otherwise
- ;
- end; { case }
- end; { DoEditChoice }
-
- procedure DoFontChoice (menuItem: Integer);
- var
- window: WindowPtr;
- fontName: Str255;
- ts: TextStyle;
- err: OSErr;
- begin
- window := FrontWindow;
- if (window <> nil) then
- begin
- GetItem(GetMHandle(kMenuFont), menuItem, fontName);
- GetFNum(fontName, ts.tsFont);
- err := WESetStyle(weDoFont, ts, DocumentPeek(window)^.hWE);
- end;
- end; { DoFontChoice }
-
- procedure DoSizeChoice (menuItem: Integer);
- var
- window: WindowPtr;
- sizeString: Str255;
- longSize: LongInt;
- mode: Integer;
- ts: TextStyle;
- err: OSErr;
- begin
- window := FrontWindow;
- if (window <> nil) then
- begin
-
- if (menuItem <= kItemLastSize) then
- begin
- GetItem(GetMHandle(kMenuSize), menuItem, sizeString);
- StringToNum(sizeString, longSize);
- mode := weDoSize;
- ts.tsSize := longSize;
- end
- else if (menuItem = kItemSmaller) then
- begin
- mode := weDoAddSize;
- ts.tsSize := -1;
- end
- else if (menuItem = kItemLarger) then
- begin
- mode := weDoAddSize;
- ts.tsSize := +1;
- end;
-
- err := WESetStyle(mode, ts, DocumentPeek(window)^.hWE);
-
- end;
- end; { DoSizeChoice }
-
- procedure DoStyleChoice (menuItem: Integer);
- var
- window: WindowPtr;
- ts: TextStyle;
- err: OSErr;
- begin
- window := FrontWindow;
- if (window <> nil) then
- begin
-
- case menuItem of
-
- kItemPlainText:
- ts.tsFace := [];
-
- kItemBold:
- ts.tsFace := [bold];
-
- kItemItalic:
- ts.tsFace := [italic];
-
- kItemUnderline:
- ts.tsFace := [underline];
-
- kItemOutline:
- ts.tsFace := [outline];
-
- kItemShadow:
- ts.tsFace := [shadow];
-
- kItemCondensed:
- ts.tsFace := [condense];
-
- kItemExtended:
- ts.tsFace := [extend];
-
- otherwise
- Exit(DoStyleChoice);
- end; { case menuItem }
-
- err := WESetStyle(weDoFace + weDoToggleFace, ts, DocumentPeek(window)^.hWE);
-
- end;
- end; { DoStyleChoice }
-
- procedure DoAlignChoice (menuItem: Integer);
- var
- window: WindowPtr;
- alignment: SignedByte;
- begin
- window := FrontWindow;
- if (window <> nil) then
- begin
-
- case menuItem of
-
- kItemAlignLeft:
- alignment := weFlushLeft;
-
- kItemCenter:
- alignment := weCenter;
-
- kItemAlignRight:
- alignment := weFlushRight;
-
- kItemJustify:
- alignment := weJustify;
-
- otherwise
- Exit(DoAlignChoice);
- end; { case }
-
- { set the alignment mode (this automatically redraws the text) }
- WESetAlignment(alignment, DocumentPeek(window)^.hWE);
-
- end;
- end; { DoAlignChoice }
-
- procedure DoMenuChoice (menuChoice: LongInt);
- var
- menuID, menuItem: Integer;
- begin
-
- { extract menu ID and menu item from menuChoice }
- menuID := HiWord(menuChoice);
- menuItem := LoWord(menuChoice);
-
- { dispatch on menuID }
- case menuID of
-
- kMenuApple:
- DoAppleChoice(menuItem);
-
- kMenuFile:
- DoFileChoice(menuItem);
-
- kMenuEdit:
- DoEditChoice(menuItem);
-
- kMenuFont:
- DoFontChoice(menuItem);
-
- kMenuSize:
- DoSizeChoice(menuItem);
-
- kMenuStyle:
- DoStyleChoice(menuItem);
-
- kMenuAlignment:
- DoAlignChoice(menuItem);
-
- otherwise
- ;
- end; { case menuID }
-
- HiliteMenu(0);
-
- end; { DoMenuChoice }
-
- function InitializeMenus: OSErr;
- begin
- InitializeMenus := noErr;
-
- { build up the whole menu bar from the 'MBAR' resource }
- SetMenuBar(GetNewMBar(kMenuBarID));
-
- { add names to the Apple and Font menus }
- AddResMenu(GetMHandle(kMenuApple), kTypeDeskAccessory);
- AddResMenu(GetMHandle(kMenuFont), kTypeFont);
-
- { draw the menu bar }
- DrawMenuBar;
-
- end; { InitializeMenus }
-
- end.